function graphMat=DecompSeries(Y,funcModel,parMode,solveOpt,addSol,inStru,KFStru,sampleStru,graphStru,nameStru)
%% DecompSeries Description 
%
% function graphMat=DecompSeries(Y,funcModel,parMode,solveOpt,addSol,inStru,KFStru,...
% sampleStru,graphStru,nameStru)
%
% Plot the decompositon of the Kalman filter srtcuture KFStru 
% either for the observables, in which case Y is an input, or selected
% states, in which case Y is empty. 
% Can plot either when feed only one shock or all except that shock. 
% Plots can be organized by shocks or by series. 
% 
%% 1. inStru       Structure with Inputs
% *.caseDecomp*  Decomposition
%
%               'single' plot series as explained by that shock 
%               'except' plot series as explained by ALL but that shock 
%
% *.orgBy*      'shocks' or 'series'               
%
% *.extract*    if Y is not observed, then cell with names of states to extract 
%
% 
%% 2. KFStru, Kalman Filter Structure 
% 
% *.countObs* counterfactual for the observables, must add up to Y demeaned
% 
% *.countSt* counterfactual for the states 
% 
%% 3. NameStru 
%
% *.obsNames* Cell with names of observables in Z Matrix     
%
% *.stateNames* Cell with names of all states, i.e. rows of solution
% matrix 
%
% *.shockNames* Cell with names of all shocks          
%
%% 4. SampleStru
%
% *.sampleVec* Numeric Vector with Sample        
%
%% 5. graphStru 
%
% *.NYears* Number of years for which to plot X-axis        
%
% All additional inputs to bve used with plotColsorPages.m are assigned
% inside the code .
% 
% ===========================================================================================
%% 1. Determine if passing an observable, if so demean
if isempty(Y)==false
    %flagObservable=true;
    YDemeaned=demeanDSGEY(Y,funcModel,parMode,solveOpt,addSol);
    decompOrig=KFStru.countObs;
    nameStru.colNames=nameStru.obsNames;
else
    %flagObservable=false;
    posExtract=cellposition(inStru.extract,nameStru.stateNames);
    decompOrig=KFStru.countSt(:,posExtract,:);
    YDemeaned=squeeze(sum(decompOrig,3));
    nameStru.colNames=inStru.extract;
end
if (isfield(inStru,'override') && inStru.override==1)
    nameStru.pageNames={inStru.GraphTitle};
else
    nameStru.pageNames=nameStru.shockNames; 
end
%% 2. Check Y can be decomposed
maxdif=max(abs(YDemeaned-sum(decompOrig,3)));
if maxdif > 1e-5
    warning('Cannot recover Level with Counterfactual')
end
%% 3. Type of Decomposition: single or except 
if strcmpi(inStru.caseDecomp,'single');
    decompMat=decompOrig;
    graphStru.suptitle=':one shock at a time'; 
elseif strcmpi(inStru.caseDecomp,'except')==1 || strcmpi(inStru.caseDecomp,'exclude')==1
    graphStru.suptitle=':excluding this shock ';
        decompMat=zeros(size(decompOrig));
        for ii=1:size(decompOrig,2);             
            for jj=1:size(decompOrig,3); 
                tempPos=setdiff( (1:size(decompMat,3))' , jj );
                decompMat(:,ii,jj)=squeeze(sum( decompOrig(:,ii,tempPos),3));                 
            end 
        end 
elseif strcmpi(inStru.caseDecomp,'custom')==1
    graphStru.suptitle = '';
    tempPos = ismember(nameStru.shocks,inStru.ShockSum);
    for ii = 1:size(decompOrig,2);
        decompMat(:,ii) = squeeze(sum(decompOrig(:,ii,tempPos),3));
    end
    graphStru.override = inStru.override;
    
else
    error('Need define inStru.caseDecomp (string) single or except');
end 
[NR NC NP]=size(decompMat); 

%% 4. Plots by series (cols) or shocks (pages) 
if strcmp(lower(inStru.orgBy),'series');
    graphStru.orgBy='cols';
    NSub=NP;
elseif strcmp(lower(inStru.orgBy),'shocks');
    graphStru.orgBy='pages';
    NSub=NC;
else
    error('Need define inStru.orgBy (string) series or shocks');
end
%% 5. Assign Graphics defaults 
if isfield(graphStru,'NYears')==false || isempty(graphStru.NYears)
    if unique(fix(sampleStru.sampleVec)) <= 5
        graphStru.NYears=length(unique(fix(sampleStru.sampleVec)));
    else
        graphStru.NYears=5;
    end
end
junk=assignXAxis(sampleStru.sampleVec,5);
graphStru.suptitleFlush='right'; 
graphStru.xtickValues=junk.xtickValues;
graphStru.xtickLabels=junk.xtickLabels;
graphStru.legend={'Data','CounterFactual'};
graphStru.legendPosition='bottom';
graphStru.xOffset=0.1; 
graphStru.yOffset=0.1; 
graphStru.flagBoxOff=1; 
graphStru.lineWidths=[1.5 2.5]; 
graphStru.hlineOn=0; 
NShocks=size(decompMat,3); 
% Feb 15 2012 
if (isfield(inStru,'override') && inStru.override==1)
    graphStru.NFigCols=ceil(sqrt(NC));
    graphStru.NFigRows=graphStru.NFigCols;
elseif NShocks < 12
    graphStru.NFigCols=2;
    graphStru.NFigRows=min( 4, ceil(NSub/graphStru.NFigCols) );
elseif NShocks < 20
    graphStru.NFigCols=2;
    graphStru.NFigRows=min(5, ceil(NSub/graphStru.NFigCols) );
elseif NShocks < 24
    graphStru.NFigCols=2;
    graphStru.NFigRows=min(6, ceil(NSub/graphStru.NFigCols) );
else
    graphStru.NFigCols=3;
    graphStru.NFigRows=min(6, ceil(NSub/graphStru.NFigCols) );
end
graphStru.xaxis=sampleStru.sampleVec;
graphMat=plotColsOrPages(YDemeaned,decompMat,graphStru,nameStru);
% Added by Leo Oct-2017
%if strcmpi(inStru.caseDecomp,'single') && strcmp(lower(inStru.orgBy),'series');
%    save ComparativeStatistics_EstimatedModel\SmoothedDecomps\YDemeaned_series YDemeaned
%    save ComparativeStatistics_EstimatedModel\SmoothedDecomps\decompMat_One_Shock_At_A_Time_series decompMat
%     'Saved Output'
%elseif strcmpi(inStru.caseDecomp,'single') && strcmp(lower(inStru.orgBy),'shocks');
%    save ComparativeStatistics_EstimatedModel\SmoothedDecomps\YDemeaned_shocks YDemeaned
%    save ComparativeStatistics_EstimatedModel\SmoothedDecomps\decompMat_One_Shock_At_A_Time_shocks decompMat
%     'Saved Output'
%elseif strcmpi(inStru.caseDecomp,'except')==1 || strcmpi(inStru.caseDecomp,'exclude')==1 && strcmp(lower(inStru.orgBy),'series');
%    save ComparativeStatistics_EstimatedModel\SmoothedDecomps\YDemeaned_series YDemeaned
%    save ComparativeStatistics_EstimatedModel\SmoothedDecomps\decompMat_excluding_the_shock_series decompMat
%    
%elseif strcmpi(inStru.caseDecomp,'except')==1 || strcmpi(inStru.caseDecomp,'exclude')==1 && strcmp(lower(inStru.orgBy),'shocks');
%    save ComparativeStatistics_EstimatedModel\SmoothedDecomps\YDemeaned_shocks YDemeaned
%    save ComparativeStatistics_EstimatedModel\SmoothedDecomps\decompMat_excluding_the_shock_shocks decompMat
%end